package model;

import java.awt.Point;
import java.util.List;

import org.jgrapht.alg.DijkstraShortestPath;
import org.jgrapht.graph.DefaultWeightedEdge;
import org.jgrapht.graph.SimpleDirectedWeightedGraph;




public class GraphUtility {


	
	
	public static SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge> genGraph(final CityMap map){
		final SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge> graph = new SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge>(DefaultWeightedEdge.class);
		for(int i = 0; i <= Config.numPalaces; i++)
			for(int j = 0; j <= Config.numPalaces; j++)
				graph.addVertex(new Crossroads(i,j));
		
		for(final Crossroads p1: graph.vertexSet()){
		
		    final int x = p1.x;
		    final int y = p1.y;
		    
		    Crossroads p2 = new Crossroads(x+1, y);
			if (graph.containsVertex(p2)){
				graph.addEdge(p1,p2);
				graph.setEdgeWeight(graph.getEdge(p1,p2), Config.nCellsPalace + (map.carsBetween(p1, p2)*Config.carTrafficRatio));
			}
			
			p2 = new Crossroads(x-1, y);
			if (graph.containsVertex(p2)){
				graph.addEdge(p1,p2);
				graph.setEdgeWeight(graph.getEdge(p1,p2), Config.nCellsPalace + (map.carsBetween(p1, p2)*Config.carTrafficRatio));
			}
			
			p2 = new Crossroads(x, y+1);
			if (graph.containsVertex(p2)){
				graph.addEdge(p1,p2);
				graph.setEdgeWeight(graph.getEdge(p1,p2), Config.nCellsPalace + (map.carsBetween(p1, p2)*Config.carTrafficRatio));
			}
			
			p2 = new Crossroads(x, y-1);
			if (graph.containsVertex(p2)){
				graph.addEdge(p1,p2);
				graph.setEdgeWeight(graph.getEdge(p1,p2), Config.nCellsPalace + (map.carsBetween(p1, p2)*Config.carTrafficRatio));
			}
		}
		
	
		return graph;
	}
	
	
	public static List<DefaultWeightedEdge> findRoute(SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge> graph, Crossroads start, Crossroads end, List<Street> banList){
		
		@SuppressWarnings("unchecked")
		SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge> temp = (SimpleDirectedWeightedGraph<Crossroads, DefaultWeightedEdge>) graph.clone();
		
		for(Street s: banList)
			temp.removeAllEdges(s.getStart(), s.getEnd());
		
		return DijkstraShortestPath.findPathBetween(temp, start, end);
		
	}
	
	
	
	public static Point graphCordsToMatrixCords(Street street, int index){
		final int buildSize = Config.nCellsPalace;
		final int road = Config.nCellsRoad;
		
		int lastX=0;
		int lastY=0;
		
		int direction = 0; // go left o down
		
		if(street.getStart().getY()==(street.getEnd().getY())){ 		// H street
			final int min = Math.min(street.getStart().getX(), street.getEnd().getX());
			
			
			if(street.getStart().getX()<street.getEnd().getX()){  	//    	dir =  ->
				direction = 1;
				lastX = min * buildSize +road * (min+1) + index;
			}else{	 												//		dir =  <-
				lastX = min * buildSize +road * (min+1) + ((Config.nCellsPalace-1) - index);
			}
			
			lastY = street.getStart().getY()* buildSize +road * (street.getStart().getY()) + direction;
		}else{ 														// V Street

			final int min = Math.min(street.getStart().getY(), street.getEnd().getY());
			lastY = min * buildSize +road * (min+1) + index;
			
			if(street.getStart().getY()<street.getEnd().getY()){ 		 //    dir =  V
				lastY = min * buildSize +road * (min+1) + index;
			}
			else{//	   dir =  ^
				lastY = min * buildSize +road * (min+1) + ((Config.nCellsPalace-1) - index);
				direction=1;
			}
			lastX = street.getStart().getX()* buildSize +road * (street.getStart().getX()) + direction;
		}
		
		return new Point(lastX,lastY);
		
	}

}
